﻿using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data;
using EFFC.Frame.Net.Module.Business.Datas;
using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using EFFC.Frame.Net.Unit.DB.Parameters;
using EFFC.Frame.Net.Base.Constants;
using System.Text;

namespace XHRPMIS.Business.v1._0
{
    public class DictionaryTable : MyRestLogic
    {
        [ActionAuth("DictionaryTable")]
        [EWRARouteDesc("获取所有词典表信息的列表")]
        [EWRAOutputDesc("返回结果", @"{
result:[{
    dic_uid:'表的uid',
    dic_name:'表名',
    dic_desc:'表描述',
    is_tree:'词典数据是否为树结构，即比普通的词典表多一个p_code栏位',
    is_locked:'是否锁定',
    is_created:'是否已创建'
}]
}")]
        public override List<object> get()
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                    select new
                    {
                        t.dic_uid,
                        t.dic_name,
                        t.dic_desc,
                        is_tree = t.istree,
                        is_created = t.iscreated,
                        is_locked = t.islocked
                    };
            return s.GetQueryList(up).Select((d) =>
            {
                dynamic dobj = d;
                dobj.is_created = BoolStd.IsNotBoolThen(dobj.is_created);
                dobj.is_locked = BoolStd.IsNotBoolThen(dobj.is_locked);
                dobj.is_tree = BoolStd.IsNotBoolThen(dobj.is_tree);
                return dobj;

            }).ToList<object>();

        }
        [ActionAuth("DictionaryTable")]
        [EWRAEmptyValid("name")]
        [EWRARouteDesc("新增一个词典表信息")]
        [EWRAAddInput("name", "string", "表名", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("desc", "string", "表描述", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAAddInput("istree", "bool", "是否为树结构", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
dicuid:""成功时候返回的UID""
}")]
        public override object post()
        {
            var dicname = ComFunc.nvl(PostDataD.name);
            var dicdesc = ComFunc.nvl(PostDataD.desc);
            var dicuid = Guid.NewGuid().ToString();
            var istree = BoolStd.IsNotBoolThen(PostDataD.istree);

            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            if ((from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                 where t.Dic_Name == dicname
                 select t).IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "表名已存在"
                };
            }
            DB.QuickInsert(up, "EXTEND_DICTIONARY_TABLE", new
            {
                DIC_UID = dicuid,
                DIC_Name = dicname,
                DIC_Desc = dicdesc,
                IsTree = istree ? 1 : 0,
                IsCreated = 0,
                IsLocked = 0,
                add_id = TokenPayLoad.ID,
                add_ip = ClientInfo.IP,
                add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                last_id = TokenPayLoad.ID,
                last_ip = ClientInfo.IP,
                last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            });
            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功",
                dicuid = dicuid
            };
        }
        [ActionAuth("DictionaryTable")]
        [EWRARouteDesc("删除一个元数据表,如果table已经创建，则table也会drop掉（如果table中有比较多的数据会比较耗时）")]
        [EWRAAddInput("id", "string", "元数据表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"根据http的状态码来识别，204标识操作成功，404表示操作识别未找到删除的资料")]
        public override bool delete(string id)
        {
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id && t.islocked.isnull(0) == 0
                    select t;
            var list = s.GetQueryList(up);
            if (!s.IsExists(up))
            {
                return false;
            }
            dynamic info = list.First();
            var iscreated = BoolStd.IsNotBoolThen(info.iscreated);

            s.Delete(up);

            //drop相关的table
            if (iscreated && DB.IsTableExists(up, info.dic_name))
            {
                DB.DropTable(up, info.dic_name);
            }

            CommitTrans();
            return true;
        }
        [ActionAuth("DictionaryTable")]
        [EWRAEmptyValid("name")]
        [EWRARouteDesc("修改一个表的信息，如果表已经创建或则不能做修改动作")]
        [EWRAAddInput("id", "string", "表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("name", "string", "元数据表名", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("desc", "string", "元数据表描述", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAAddInput("istree", "bool", "是否为树结构", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
dicuid:""成功时候返回的UID""
}")]
        public override object patch(string id)
        {
            var dicname = ComFunc.nvl(PostDataD.name);
            var dicdesc = ComFunc.nvl(PostDataD.desc);
            var istree = BoolStd.IsNotBoolThen(PostDataD.istree);

            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id
                    select t;
            var list = s.GetQueryList(up);
            if (!s.IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "表不存在"
                };
            }
            dynamic info = list.First();
            bool iscreated = BoolStd.IsNotBoolThen(info.iscreated);
            if (iscreated)
            {
                return new
                {
                    code = "failed",
                    msg = "表已经创建，不可修改"
                };
            }

            if ((from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                 where t.Dic_Name == dicname && t.dic_uid != id
                 select t).IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "表名已存在"
                };
            }

            DB.QuickUpdate(up, "EXTEND_DICTIONARY_TABLE", new
            {
                DIC_Name = dicname,
                DIC_Desc = dicdesc,
                IsTree = istree ? 1 : 0,
                last_id = TokenPayLoad.ID,
                last_ip = ClientInfo.IP,
                last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            }, new
            {
                dic_uid = id,
            });

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功",
                dicuid = id
            };
        }
        [ActionAuth("DictionaryTable")]
        [EWRARoute("patch", "/dictionarytable/{id}/lock")]
        [EWRARouteDesc("锁定一个元数据表，使其不可用被删除")]
        [EWRAAddInput("id", "string", "表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
        object Lock(string id)
        {
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id
                    select t;
            var list = s.GetQueryList(up);
            if (!s.IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "表不存在"
                };
            }
            dynamic info = list.First();
            bool islocked = BoolStd.IsNotBoolThen(info.islocked);
            if (islocked)
            {
                return new
                {
                    code = "failed",
                    msg = "表已锁定，无需重复操作"
                };
            }
            s.Update(up, new
            {
                islocked = 1
            });

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
        [ActionAuth("DictionaryTable")]
        [EWRARoute("patch", "/dictionarytable/{id}/unlock")]
        [EWRARouteDesc("解锁一个表，使其可被删除")]
        [EWRAAddInput("id", "string", "表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
        object UnLock(string id)
        {
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id
                    select t;
            var list = s.GetQueryList(up);
            if (!s.IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "表不存在"
                };
            }
            dynamic info = list.First();
            bool islocked = BoolStd.IsNotBoolThen(info.IsLocked);
            if (!islocked)
            {
                return new
                {
                    code = "failed",
                    msg = "表已解锁，无需重复操作"
                };
            }
            s.Update(up, new
            {
                islocked = 0
            });

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
        [ActionAuth("DictionaryTable")]
        [EWRARoute("patch", "/dictionarytable/{id}/create")]
        [EWRARouteDesc("创建一个表，并自动锁定（表未锁定时才能操作）")]
        [EWRAAddInput("id", "string", "表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
        object CreateTable(string id)
        {
            BeginTrans();
            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            var msg = "";
            if (!DoCreateTable(metaup, up, id, ref msg))
            {
                return new
                {
                    code = "failed",
                    msg
                };
            }

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
        public bool DoCreateTable(UnitParameter metaup, UnitParameter up, string id, ref string msg)
        {
            var s = from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id
                    select t;
            var list = s.GetQueryList(metaup);
            if (!s.IsExists(metaup))
            {
                msg = "表不存在";
                return false;
            }
            dynamic info = list.First();
            bool islocked = BoolStd.IsNotBoolThen(info.islocked);
            if (islocked)
            {
                msg = "表已锁定，不可进行操作";
                return false;
            }
            bool iscreated = BoolStd.IsNotBoolThen(info.iscreated);
            if (iscreated)
            {
                msg = "表已创建，不可进行操作";
                return false;
            }
            if (DB.IsTableExists(up, info.dic_name))
            {
                msg = "表已存在，不可进行操作";
                return false;
            }

            bool istree = BoolStd.IsNotBoolThen(info.istree);
            if (istree)
            {
                DB.CreateTable(up, info.dic_name, new TableColumn() { Name = "code", DataType = "varchar", Precision = 50, IsPK = true, AllowNull = false },
                    new TableColumn() { Name = "value", DataType = "nvarchar", Precision = 100, IsPK = false, AllowNull = true },
                    new TableColumn() { Name = "level", DataType = "int", Default = "0", IsPK = false, AllowNull = true },
                    new TableColumn() { Name = "p_code", DataType = "varchar", Precision = 50, IsPK = false, AllowNull = true },
                    new TableColumn() { Name = "sort_no", DataType = "int", Default = "0", IsPK = false, AllowNull = true });
            }
            else
            {
                DB.CreateTable(up, info.dic_name, new TableColumn() { Name = "code", DataType = "varchar", Precision = 50, IsPK = true, AllowNull = false },
                    new TableColumn() { Name = "value", DataType = "nvarchar", Precision = 100, IsPK = false, AllowNull = true },
                    new TableColumn() { Name = "sort_no", DataType = "int", Default = "0", IsPK = false, AllowNull = true });
            }

            s.Update(metaup, new
            {
                islocked = 1,
                iscreated = 1
            });
            return true;
        }
        [ActionAuth("DictionaryTable")]
        [EWRARoute("patch", "/dictionarytable/{id}/drop")]
        [EWRARouteDesc("Drop一个表，表未锁定时才能操作")]
        [EWRAAddInput("id", "string", "表的UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
        object DropTable(string id)
        {
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var msg = "";
            if (!DoDropTable(up, id, ref msg))
            {
                return new
                {
                    code = "failed",
                    msg
                };
            }

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }

        public bool DoDropTable(UnitParameter metaup, string id, ref string msg)
        {
            var s = from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                    where t.dic_uid == id
                    select t;
            var list = s.GetQueryList(metaup);
            if (!s.IsExists(metaup))
            {
                return false;
            }
            dynamic info = list.First();
            bool islocked = BoolStd.IsNotBoolThen(info.islocked);
            if (islocked)
            {
                msg = "表已锁定，不可进行操作";
                return false;
            }
            bool iscreated = BoolStd.IsNotBoolThen(info.iscreated);
            if (!iscreated)
            {
                msg = "表未创建，不可进行操作";
                return false;
            }
            if (DB.IsTableExists(metaup, info.dic_name))
            {
                DB.DropTable(metaup, info.dic_name);

                s.Update(metaup, new
                {
                    iscreated = 0
                });
            }
            else
            {
                msg = "表不存在，不可进行操作";
                return false;
            }
            return true;
        }

        [EWRAAuth(true)]
        [EWRARoute("patch", "/dictionarytable/script/export")]
        [EWRARouteDesc("将指定的词典表生成脚本并下载")]
        [EWRAAddInput("ids", "string", "元数据表的UID,多个用逗号分隔", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
filetype:'文件类型',
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
        object GenScriptsByIDs()
        {
            string ids = ComFunc.nvl(PostDataD.ids);
            if (ids == "") return new
            {
                code = "failed",
                msg = "请选择要导出的表单"
            };
            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            var diclist = new List<object>();
            var list = (from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                        where t.DIC_UID.within(ids)
                        select t).GetQueryList(metaup);
            foreach (dynamic item in list)
            {
                var additem = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);

                item.IsTree = BoolStd.IsNotBoolThen(item.IsTree);
                item.IsCreated = BoolStd.IsNotBoolThen(item.IsCreated);
                item.IsLocked = BoolStd.IsNotBoolThen(item.IsLocked);
                item.add_time = DateTimeStd.IsDateTimeThen(item.add_time, "yyyy-MM-dd HH:mm:ss");
                item.last_time = DateTimeStd.IsDateTimeThen(item.last_time, "yyyy-MM-dd HH:mm:ss");

                additem.DicInfo = item;
                string tablename = ComFunc.nvl(item.DIC_Name);
                additem.DataList = (from t in DB.LamdaTable(up, tablename, "a")
                                    select t).GetQueryList(up);
                diclist.Add(additem);
            }

            var dobj = FrameDLRObject.CreateInstance(EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
            dobj.DicList = diclist;
            var sign_str = ComFunc.getMD5_String(((FrameDLRObject)dobj).ToJSONString(true));
            dobj.ValidSign = sign_str;

            return FileHelper.DoDownLoad("dictionary_table.json", Encoding.UTF8.GetBytes(((FrameDLRObject)dobj).ToJSONString(true)));
        }

        [EWRARoute("patch", "/dictionarytable/script/import")]
        [EWRAEmptyValid("data")]
        [EWRARouteDesc("导入动态表单的脚本")]
        [EWRAAddInput("data", "json", @"导入的文件，格式如下：{
filetype:'文件类型',
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
        object ImportScript()
        {
            dynamic data = FrameDLRObject.IsJsonThen(PostDataD.data);
            if (data == null) return new
            {
                code = "failed",
                msg = "上传格式不正确"
            };
            var file = ComFunc.nvl(data.file);
            if (string.IsNullOrEmpty(file)) return new
            {
                code = "failed",
                msg = "上传文件无效，终止操作"
            };
            var content = ComFunc.IsBase64Then(file);
            if (content == "") return new
            {
                code = "failed",
                msg = "上传文件格式无效，终止操作"
            };
            var scripts = FrameDLRObject.IsJsonThen(content, null, EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
            if (scripts == null) return new
            {
                code = "failed",
                msg = "上传文件格式无效，终止操作"
            };
            var valid_sign = ComFunc.nvl(scripts.GetValue("ValidSign"));
            if (valid_sign == null) return new
            {
                code = "failed",
                msg = "上传文件不合法，终止操作"
            };
            ((FrameDLRObject)scripts).Remove("ValidSign");
            var sign_str = ComFunc.getMD5_String(scripts.ToJSONString(true));
            if (sign_str != valid_sign) return new
            {
                code = "failed",
                msg = "上传文件校验失败，终止操作"
            };
            var diclist = (IEnumerable<object>)scripts.GetValue("DicList");
            //BeginTrans();
            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            foreach (dynamic s in diclist)
            {
                var msg = "";
                var ss = from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                         where t.DIC_UID == s.DicInfo.DIC_UID
                         select t;
                dynamic existinfo = ss.GetQueryList(metaup).FirstOrDefault();
                if (existinfo != null)
                {
                    if (DB.IsTableExists(up, existinfo.dic_name))
                    {
                        DB.DropTable(up, existinfo.dic_name);
                    }
                    ss.Delete(metaup);
                }
                s.DicInfo.IsTree = BoolStd.ConvertTo(s.DicInfo.IsTree, 1, 0);
                s.DicInfo.IsCreated = 0;
                s.DicInfo.IsLocked = 0;

                DB.QuickInsert(metaup, "EXTEND_DICTIONARY_TABLE", s.DicInfo);
                if (!DoCreateTable(metaup, up, s.DicInfo.DIC_UID, ref msg))
                {
                    return new
                    {
                        code = "failed",
                        msg
                    };
                }

                var datalist = (IEnumerable<object>)s.DataList;

                foreach (var item in datalist)
                {
                    DB.QuickInsert(up, s.DicInfo.DIC_Name, item);
                }
            }
            //CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
    }
}